package com.ww.java.generic.wildcard;

import java.util.ArrayList;
import java.util.List;

/**
 * flist类型现在是List<? extends Fruit>，你可以将其读作“具有任何从Fruit继承的类型的列表”。
 * 但是，这实际上并不意味着这个List将持有任何类型的Fruit。通配符引用是为了明确类型，
 * 因此它意味着“某种flist引用没有指定的具体类型”。因此这个被赋值的List必须持有诸如Fruit
 * 或Apple这样的某种指定类型，但是为了向上转型为flist，这个类型具体是什么并没人关心。
 * 
 * 如果唯一的限制是这个List要持有某种具体的Fruit或Fruit的子类型，但是你实际上并不关心它
 * 是什么，那么你能用这样的List做什么呢？如果不知道List持有什么类型，那么你怎样才能安全
 * 向其中添加对象呢？你不能，除非编译而不是运行时系统可以阻止这种操作的发生。
 * 
 * 因为现在你甚至不能向刚刚声明过将持有Apple对象的List中放置一个Apple对象了。是的，但是编译器
 * 并不知道这一点，List<? extends Fruit>可以合法的指向一个List<Orange>。一旦执行这种类型的向上转型，
 * 你就将丢失掉向其中传递任何对象的能力，甚至是传递Object也不行。
 */
public class GenericsAndCovariance {

	@SuppressWarnings("unused")
	public static void main(String[] args) {
		List<? extends Fruit> flist = new ArrayList<>();
		// The method add(capture#1-of ? extends Fruit) in the type List<capture#1-of ? extends Fruit> is not applicable for the arguments (Apple)
//		flist.add(new Apple());
		
//		flist.add(new Fruit());
		
//		flist.add(new Object());
		
		// 合法，但是没有意义
		flist.add(null);
		
		Fruit f = flist.get(0);
	}
}